package com.ala4.oxcafe.boot.endpoint;

import com.ala4.oxcafe.boot.async.ExportFutureManager;
import com.ala4.oxcafe.enums.AsyncTaskStateEnum;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.annotation.Selector;
import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
import org.springframework.util.Assert;

import java.util.List;
import java.util.concurrent.Future;

/**
 * 异步端点管理-主要是给健康检查的时候使用
 *
 * @author PING
 * @date 2024/12/21 21:05
 */
@Endpoint(id = "async-export-endpoint")
public class AsyncExportEndpoint {

    private static final String NOT_FOUND = "404";
    private static final String SUCCESS = "success";
    private static final String FAILED = "failed";

    private final ExportFutureManager futureManager;

    public AsyncExportEndpoint(ExportFutureManager exportFutureManager) {
        this.futureManager = exportFutureManager;
    }

    /**
     * GET:/actuator/async-export-endpoint
     *
     * @return all-key
     */
    @ReadOperation
    public List<String> getExportTaskIds() {
        return futureManager == null ? null : futureManager.getAllKeys();
    }

    /**
     * 404 or done or cancelled or doing
     * GET:/actuator/async-export-endpoint/uuid
     *
     * @param uuid
     * @return uuid
     */
    @ReadOperation
    public String getExportTaskState(@Selector String uuid) {
        Assert.notNull(uuid, "UUID must not be empty");
        Future<?> future;
        if (futureManager == null || (future = futureManager.get(uuid)) == null) {
            return NOT_FOUND;
        }
        if (future.isDone()) {
            return AsyncTaskStateEnum.DONE.getCode();
        }
        if (future.isCancelled()) {
            return AsyncTaskStateEnum.CANCELLED.getCode();
        }
        return AsyncTaskStateEnum.DOING.getCode();
    }

    /**
     * success or failed
     * POST:/actuator/async-export-endpoint
     * success when task canceled or removed
     * failed when task done or canceled failed
     */
    @WriteOperation
    public ExportFutureManager.TaskState cancelExportTask(@Selector String uuid) {
        Assert.notNull(uuid, "UUID must not be empty");
        if (futureManager != null) {
            return futureManager.cancel(uuid);
        }
        return ExportFutureManager.TaskState.FAILED;
    }

}
